package com.tbit.main.service.impl;

import com.tbit.main.constant.DaoParamConstant;
import com.tbit.main.dao.history.HistoryDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.GeoUtil;
import com.tbit.main.util.LogUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;

@Service("historyService")
public class HistoryServiceImpl implements HistoryService {
    @Autowired
    private HistoryDao historyDao;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private BatteryModelDetalService batteryModelDetalService;

    @Override
    public List<TerPosition> getByMachineNOAndTime(Integer mapType, String machineNO, String startTime, String endTime,Integer machineId) {
        //获取查询的时间分段参数
        List<Map<String, Object>> searchParams = this.getSearchParams(machineNO, startTime, endTime,"machineNO",true);
        List<TerPosition> historyList = new ArrayList<>();
        for (Map<String, Object> param : searchParams) {
            List<TerPosition> history = historyDao.getByMachineNOAndTime(param);
            if (CollectionUtils.isNotEmpty(history)) {
                calibrateService.calibrateOffSet(history, mapType);
                historyList.addAll(history);
            }
        }
        //获取车辆各个轨迹点的电量
        this.getMachineSoc(historyList,machineId);

        return historyList;
    }

    @Override
    public Integer getMileageByMachineNOAndTime(String machineNO, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("machineNO", machineNO);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);

        return historyDao.getMileageByMachineNOAndTime(params);
    }

    @Override
    public Integer getMileageByMachineNOAndTimeTwo(String machineNO, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("machineNO", machineNO);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        TerPosition terPositionFirst = historyDao.getMileageByMachineNOAndTimeFirst(params);
        TerPosition terPositionEnd = historyDao.getMileageByMachineNOAndTimeEnd(params);
        if (terPositionFirst != null && terPositionEnd != null) {
            double desc = GeoUtil.getDistance(new Point(terPositionFirst.getLon(), terPositionFirst.getLat()), new Point(terPositionEnd.getLon(), terPositionEnd.getLat()));
            Integer distance = (int) Math.round(desc);
            return distance;
        } else {
            return 0;
        }
    }

    @Override
    public List<TerPosition> getLastRideHistory(Integer mapType, String machineNO) {
        /**查询设备信息*/
        Machine machine = machineService.getByMachineNO(machineNO);
        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }

        /**查询设备最后一次骑行轨迹*/
        RideLog rideLog = rideLogService.findLastByMachineId(machine.getMachineId());

        if (rideLog == null) {
            LogUtil.info("machineNO=" + machineNO + ",无最后订单");
            return new ArrayList<TerPosition>();
        }

        String startTime = rideLog.getStartTime();
        String endTime = DateTimeUtil.getNowTime();

        /**判断设备是否正在骑行*/
        MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
        if (machineBorrow == null) {
            endTime = rideLog.getEndTime();
        }

        return getByMachineNOAndTime(mapType, machineNO, startTime, endTime,machine.getMachineId());
    }

    @Override
    public List<TerPosition> getLastActiveHistory(Integer mapType, String machineNO) {
        /**查询设备信息*/
        Machine machine = machineService.getByMachineNO(machineNO);
        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }

        /**判断设备是否正在骑行*/
        MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
        if (machineBorrow != null) {
            return new ArrayList<TerPosition>();
        }

        /**查询设备最后一次骑行轨迹*/
        RideLog rideLog = rideLogService.findLastByMachineId(machine.getMachineId());

        String startTime = null;
        if (rideLog != null) {
            startTime = rideLog.getEndTime();
        }

        String endTime = DateTimeUtil.getNowTime();

        return getByMachineNOAndTime(mapType, machineNO, startTime, endTime,machine.getMachineId());
    }

    @Override
    public List<TerPosition> getByMachineNOTime(List<TerPosition> terPositions) {
        return historyDao.getByMachineNOTime(terPositions);
    }

    @Override
    public List<TerPosition> getByAccountUserPhoneAndTime(Integer mapType, String accountUserPhone, String startTime, String endTime) {
        /*Map<String, Object> params = new HashMap<String, Object>();
        params.put("accountUserId", accountUserId);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        List<TerPosition> history = historyDao.getByAccountUserIdAndTime(params);
        if (history.size() > 0) {
            calibrateService.calibrateOffSet(history, mapType);
        }

        return history;*/
        //获取查询的时间分段参数
        List<Map<String, Object>> searchParams = this.getSearchParams(accountUserPhone, startTime, endTime,"accountUserPhone",true);
        List<TerPosition> historyList = new ArrayList<>();
        for (Map<String, Object> param : searchParams) {
            List<TerPosition> history = historyDao.getByAccountUserPhoneAndTime(param);
            if (history.size() > 0) {
                calibrateService.calibrateOffSet(history, mapType);
                historyList.addAll(history);
            }
        }
        return historyList;
    }

    @Override
    public TrajectoryBO getTrajectoryByMachineNOAndTime(String machineNO, String startTime, String endTime) {
        /*Map<String, Object> params = new HashMap<>();
        params.put("machineNO", machineNO);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        List<TerPosition> terPositions = historyDao.getByMachineNOAndTime(params);*/
        //获取查询的时间分段参数
        List<Map<String, Object>> searchParams = this.getSearchParams(machineNO, startTime, endTime,"machineNO",true);
        List<TerPosition> historyList = new ArrayList<>();
        for (Map<String, Object> param : searchParams) {
            List<TerPosition> history = historyDao.getByMachineNOAndTime(param);
            if (CollectionUtils.isNotEmpty(history)) {
                historyList.addAll(history);
            }
        }

        // 轨迹
        int mileage = historyList.stream().mapToInt(TerPosition::getMile).sum();

        TerPosition firstPos = historyList.stream().min(Comparator.comparing(TerPosition::getDateTime)).orElse(null);
        TerPosition endPos = historyList.stream().max(Comparator.comparing(TerPosition::getDateTime)).orElse(null);

        // 直线距离
        int straightDistance = 0;
        if (firstPos != null) {
            double desc = GeoUtil.getDistance(new Point(firstPos.getLon(), firstPos.getLat()), new Point(endPos.getLon(), endPos.getLat()));
            straightDistance = (int) Math.round(desc);
        }
        Optional.ofNullable(mileage).orElse(0);
        return new TrajectoryBO(mileage, straightDistance);
    }

    @Override
    public void insert(TerPosition terPosition) {
        historyDao.insert(terPosition);
    }

    /**
     * @description: 根据时间范围返回分段查询参数
     * @author: mo.shanyong
     * @date: 2025/4/21 10:27
     * @param: machineNO 设别编号
     * @param: startTime 开始时间
     * @param: endTime 结束时间
     * @param: paramName 查询的参数名
     * @param: checkCount 是否检查数据量
     * @return: java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     */
    @Override
    public List<Map<String, Object>> getSearchParams(String machineNO,String start,String end,String paramName,boolean checkCount) {
        List<Map<String, Object>> searchParamList = new ArrayList<>();
        LocalDateTime startDateTime = DateTimeUtil.getLocalDateTimeByTimeStr(start);
        LocalDateTime endDateTime = DateTimeUtil.getLocalDateTimeByTimeStr(end);
        long betweenHours = ChronoUnit.HOURS.between(startDateTime, endDateTime);
        Map<String, Object> params = new HashMap<>();
        params.put(paramName, machineNO);
        params.put(DaoParamConstant.startTime, DateTimeUtil.getDateByDateStr(start));
        params.put(DaoParamConstant.endTime, DateTimeUtil.getDateByDateStr(end));
        if (betweenHours < 8L){
            searchParamList.add(params);
            return searchParamList;
        }
        if (checkCount) {
            int count = historyDao.getCountByMachineNOAndTime(params);
            if (count <= 5000) {
                searchParamList.add(params);
                return searchParamList;
            }
        }
        do {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put(paramName, machineNO);
            paramMap.put(DaoParamConstant.startTime, Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()));
            LocalDateTime localDateTime = startDateTime.plusHours(8).isAfter(endDateTime) ? endDateTime : startDateTime.plusHours(8);
            paramMap.put(DaoParamConstant.endTime,Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
            searchParamList.add(paramMap);
            if (localDateTime.isAfter(endDateTime) || localDateTime.isEqual(endDateTime)){
                break;
            }
            startDateTime = localDateTime.plusSeconds(1);
        }while (true);
        return searchParamList;
    }

    /**
     * @description: 获取车辆各个轨迹点的电量
     * @author: mo.shanyong
     * @date: 2025/4/21 14:49
     * @param: historyList
     * @param: machineId
     */
    private void getMachineSoc(List<TerPosition> historyList,Integer machineId){
        if (CollectionUtils.isEmpty(historyList)){
            return;
        }
        List<BatteryModelDetail> batteryModelDetails = batteryModelDetalService.getByMachineId(machineId);
        for (TerPosition terPosition : historyList) {
            if (terPosition.getCartV() <= 0){
                terPosition.setSoc(0);
                continue;
            }
            double cartV = terPosition.getCartV();
            if (CollectionUtils.isEmpty(batteryModelDetails)){
                terPosition.setSoc(0);
                continue;
            }
            for (BatteryModelDetail batteryModelDetail : batteryModelDetails) {
                if (batteryModelDetail.getMinVol() <= cartV && cartV <= batteryModelDetail.getMaxVol()) {
                    terPosition.setSoc(batteryModelDetail.getBatteryPer());
                    break;
                }
            }

        }

    }
}  